<?php
/*
  Compatibility: php 5.4+
        WebSite: https://codding.cn
         GitHub: https://github.com/zhaixingfy
         Author: 摘星fy
         Editor: SublimeText
           Goal: Make the best database dev tool
           Date: 2024-5-21 23:26:36
             vx: y273259755
             qq: 273259755
*/

// usleep(500e3);
header('Access-Control-Allow-Origin: *');
error_reporting(1);
define('ROOT_PATH', substr($path, 0, strrpos($path, '/')));
define('DB_TYPE', $_REQUEST['dbType'] ?? 'mysql');
define('DB_HOST', $_REQUEST['dbHost']);
define('DB_USER', $_REQUEST['dbUser']);
define('DB_PWD', $_REQUEST['dbPwd']);
define('CUR_DB', $_REQUEST['curDB']);
define('CUR_TABLE', $_REQUEST['curTable']);
define('DB_TABLE', '`'.CUR_DB.'`.`'.CUR_TABLE.'`');

$ex = json_decode($_REQUEST['ex']);
$pdo = new PDO(DB_TYPE.":host=".DB_HOST, DB_USER, DB_PWD);
// $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); // pdo 静默报错

if (CUR_DB) $pdo->query('use '.CUR_DB);

function now() {
  return intval(microtime(true) * 1000);
}

function err($code, $msg) {
  // JSON_UNESCAPED_UNICODE
  echo json_encode(['errCode' => $code, 'errMsg' => $msg], 256);
  exit;
}

function res($data) {
  echo json_encode(['data' => $data], 256);
  exit;
}

function quote($str) {
  global $pdo;
  return $pdo->quote(trim($str));
}

function getInsertId() {
  global $pdo;
  return intval($pdo->lastInsertId());
}

function query($sql) {
  global $pdo;

  $handler = $pdo->query($sql);

  if (!$handler) {
    $sqlResult = quote(implode(', ', $pdo->errorInfo()));
    $sqlStr = quote($sql);
    $pdo->query("INSERT INTO sql_err (sqlStr, sqlResult) VALUES ($sqlStr, $sqlResult)");
    err(1, $sql."\n".$sqlResult);
  }

  return $handler;
}

function queryRow($sql) {
  return query($sql)->fetchObject();
}

function queryList($sql) {
  $handler = query($sql);
  $result = [];
  while ($row = $handler->fetchObject()) {
    $result[] = $row;
  }
  return $result;
}

switch ($_REQUEST['a']) {
  case 'ls-def':
    res([
      'time' => now(),
      'serverLang' => 'php',
      'server' => $_SERVER,
      'gs' => queryList('SHOW GLOBAL STATUS'),
      'vars' => queryList('SHOW VARIABLES'),
      'engines' => queryList('SHOW ENGINES'),
      'charset' => queryList('SHOW CHARACTER SET'),
      'collation' => queryList('SHOW COLLATION'),
      'php_ini' => ini_get_all(),
    ]);
    break;
  case 'ls-db':
    res(array_map(function($row) {
      return $row->Database;
    }, queryList('SHOW DATABASES')));
    break;
  case 'ls-table':
    $sql = 'SHOW CREATE DATABASE `'.CUR_DB.'`';
    $handler = $pdo->query($sql);

    res([
      'scDB' => $handler ? $handler->fetchObject()->{'Create Database'} : $sql.' 获取失败',
      'list' => array_map(function($row) { return $row->{'Tables_in_'.CUR_DB}; }, queryList('SHOW TABLES')),
    ]);
    break;
  case 'ls-field':
    res([
      'scTable' => queryRow('SHOW CREATE TABLE '.CUR_TABLE),
      'list' => queryList('DESC '.CUR_TABLE),
    ]);
    break;
  case 'ls-data':
    $pageCur = (int)$_REQUEST['pageCur'];
    $pageSize = (int)$_REQUEST['pageSize'];
    $start = $pageCur * $pageSize;
    $where = implode(' AND ', array_map(function($v) {
      return "`${v[0]}`=".quote($v[1]);
    }, $ex->where));
    $orderBy = implode(',', array_map(function($v) {
      return "`${v[0]}` ".($v[1] > 0 ? 'DESC' : 'ASC');
    }, $ex->orderBy));

    res([
      'total' => intval(queryRow("SELECT count(*) AS total FROM ".DB_TABLE.($where ? ' WHERE '.$where : ''))->total),
      'list' => queryList("SELECT * FROM ".DB_TABLE.($where ? ' WHERE '.$where : '').($orderBy ? ' ORDER BY '.$orderBy : '')." LIMIT $start, $pageSize"),
    ]);
    break;
  default:
    err(2, 'uncaught action: '.$_REQUEST['a']);
    break;
}
